// ImageFrame.java
//
// Informatics 102 Spring 2012
// Assignment #2: Metadata and Reflection
//
// This class contains the application's user interface, which is contained
// entirely within one frame window.  The frame window has two components:
//
// (1) a menu bar that allows users to open and close images, exit the
//     program, and apply any of the loaded filters
//
// (2) a scrollable view that displays the image in its current form

package inf102.assignment2.ui;

import inf102.assignment2.filters.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;


public class ImageFrame extends JFrame
{
	private JMenuItem fileOpenMenuItem;
	private JMenuItem fileCloseMenuItem;
	private JMenu filterMenu;
	private JScrollPane scrollPane;
	
	private FilterableImage currentImage;
	
	
	public ImageFrame(FilterSet filterSet)
	{
		super("Informatics 102 Assignment #2");
		
		currentImage = null;
		
		buildUI(filterSet);
		updateUI();
	}
	
	
	private void buildUI(FilterSet filterSet)
	{
		setSize(1000, 700);
		buildMenu(filterSet);
		buildImageArea();
		setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		updateUI();
	}
	
	
	private void buildMenu(FilterSet filterSet)
	{
		JMenuBar menuBar = new JMenuBar();
		
		JMenu fileMenu = new JMenu("File");

		fileOpenMenuItem = new JMenuItem("Open...");
		fileOpenMenuItem.addActionListener(
			new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					fileOpen();
				}
			});
		fileMenu.add(fileOpenMenuItem);

		fileCloseMenuItem = new JMenuItem("Close");
		fileCloseMenuItem.addActionListener(
			new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					fileClose();
				}
			});
		fileMenu.add(fileCloseMenuItem);
		
		JMenuItem fileExitMenuItem = new JMenuItem("Exit");
		fileExitMenuItem.addActionListener(
			new ActionListener()
			{
				public void actionPerformed(ActionEvent e)
				{
					fileExit();
				}
			});
		fileMenu.add(fileExitMenuItem);
		
		menuBar.add(fileMenu);
		
		filterMenu = new JMenu("Filter");
		
		for (final Filter filter : filterSet.getFilters())
		{
			JMenuItem filterMenuItem = new JMenuItem(filter.getName());
			filterMenuItem.addActionListener(
				new ActionListener()
				{
					public void actionPerformed(ActionEvent e)
					{
						executeFilter(filter);
					}
				});
			filterMenu.add(filterMenuItem);
		}
		
		menuBar.add(filterMenu);
		
		setJMenuBar(menuBar);
	}
	
	
	private void buildImageArea()
	{
		GridBagLayout layout = new GridBagLayout();
		getContentPane().setLayout(layout);
		
		scrollPane = new JScrollPane(new JPanel());
		
		getContentPane().add(scrollPane);
		layout.setConstraints(
			scrollPane,
			new GridBagConstraints(
				0, 0, 1, 1, 1.0, 1.0,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH,
				new Insets(0, 0, 0, 0), 0, 0));
	}

	
	private void updateUI()
	{
		fileOpenMenuItem.setEnabled(true);
		fileCloseMenuItem.setEnabled(currentImage != null);
		filterMenu.setEnabled(currentImage != null);
		updateImageArea();
	}
	
	
	private void updateImageArea()
	{
		if (currentImage == null)
		{
			scrollPane.setViewportView(new JPanel());
		}
		else
		{
			JLabel imageLabel = new JLabel();
			imageLabel.setIcon(new ImageIcon(currentImage.convertToBufferedImage()));
			scrollPane.setViewportView(imageLabel);
		}
	}
	
	
	private void fileOpen()
	{
		JFileChooser chooser = new JFileChooser();
		
		int result = chooser.showOpenDialog(this);
		
		if (result == JFileChooser.APPROVE_OPTION)
		{
			File fileToOpen = chooser.getSelectedFile();
			
			try
			{
				currentImage = new FilterableImage(ImageIO.read(fileToOpen));
				updateUI();
			}
			catch (IOException e)
			{
				JOptionPane.showMessageDialog(
					this, "Could not open file: " + e.getMessage(),
					"Could Not Open File",
					JOptionPane.ERROR_MESSAGE);
				
				return;
			}
		}
	}
	
	
	private void fileClose()
	{
		currentImage = null;
		updateUI();
	}


	private void fileExit()
	{
		dispose();
	}


	private void executeFilter(Filter filter)
	{
		filter.execute(currentImage);
		updateUI();
	}
}
